package com.chenyaowei.product.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.chenyaowei.common.constant.CacheConstants;
import com.chenyaowei.common.core.redis.RedisCache;
import com.chenyaowei.common.exception.ServiceException;
import com.chenyaowei.common.utils.DateUtils;
import com.chenyaowei.elasticsearch.mapper.ProductMapper;
import com.chenyaowei.elasticsearch.model.Product;
import com.chenyaowei.product.domain.CywProSkuInfo;
import com.chenyaowei.product.domain.CywProSpuInfo;
import com.chenyaowei.product.domain.CywProductCategory;
import com.chenyaowei.product.mapper.CywProSpuInfoMapper;
import com.chenyaowei.product.service.CywProductService;
import com.chenyaowei.product.service.ICywProSpuInfoService;
import com.chenyaowei.product.service.ICywProductCategoryService;
import com.chenyaowei.product.vo.ProductInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * spu信息Service业务层处理
 *
 * @author 陈耀威
 * @date 2023-11-24
 */
@Service
public class CywProSpuInfoServiceImpl implements ICywProSpuInfoService {

    @Autowired
    private CywProSpuInfoMapper cywProSpuInfoMapper;

    @Autowired
    private ICywProductCategoryService categoryService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ProductMapper esProductMapper;

    @Autowired
    private CywProductService productService;

    /**
     * 查询spu信息
     *
     * @param spuId spu信息主键
     * @return spu信息
     */
    @Override
    public CywProSpuInfo selectCywProSpuInfoBySpuId(Long spuId) {
        List<CywProductCategory> list = categoryService.selectCywProductCategoryList(null);
        CywProSpuInfo cywProSpuInfo = cywProSpuInfoMapper.selectCywProSpuInfoBySpuId(spuId);
        Long catalogId = cywProSpuInfo.getCatalogId();
        //自身
        CywProductCategory source = list.stream().filter(item -> item.getCatId().equals(catalogId)).findFirst().orElse(null);
        List<Long> originCatIds = new ArrayList<>();
        originCatIds = findOriginCatIds(source, list, originCatIds);
        cywProSpuInfo.setOriginIds(originCatIds.stream().sorted().toArray(Long[]::new));
        return cywProSpuInfo;
    }

    private List<Long> findOriginCatIds(CywProductCategory source, List<CywProductCategory> list, List<Long> originCatIds){
        originCatIds.add(source.getCatId());
        CywProductCategory parent = list.stream().filter(item -> item.getCatId().equals(source.getParentCid())).findFirst().orElse(null);
        if (ObjectUtil.isNotEmpty(parent)){
            findOriginCatIds(parent, list, originCatIds);
        }
        return originCatIds;
    }

    /**
     * 查询spu信息列表
     *
     * @param cywProSpuInfo spu信息
     * @return spu信息
     */
    @Override
    public List<CywProSpuInfo> selectCywProSpuInfoList(CywProSpuInfo cywProSpuInfo) {
        return cywProSpuInfoMapper.selectCywProSpuInfoList(cywProSpuInfo);
    }

    /**
     * 新增spu信息
     *
     * @param cywProSpuInfo spu信息
     * @return 结果
     */
    @Override
    public int insertCywProSpuInfo(CywProSpuInfo cywProSpuInfo) {
        cywProSpuInfo.setCreateTime(DateUtils.getNowDate());
        return cywProSpuInfoMapper.insertCywProSpuInfo(cywProSpuInfo);
    }

    /**
     * 修改spu信息
     *
     * @param cywProSpuInfo spu信息
     * @return 结果
     */
    @Override
    public int updateCywProSpuInfo(CywProSpuInfo cywProSpuInfo) {
        cywProSpuInfo.setUpdateTime(DateUtils.getNowDate());
        // TODO es
        redisCache.deleteObject(CacheConstants.PRODUCT_CACHE + "*");
        return cywProSpuInfoMapper.updateCywProSpuInfo(cywProSpuInfo);
    }

    /**
     * 批量删除spu信息
     *
     * @param spuIds 需要删除的spu信息主键
     * @return 结果
     */
    @Override
    public int deleteCywProSpuInfoBySpuIds(Long[] spuIds) {
        List<CywProSpuInfo> proSpuInfoList = cywProSpuInfoMapper.selectListBySpuIds(Arrays.asList(spuIds));
        proSpuInfoList.forEach(item -> {
            if (item.getPublishStatus() == 1) {
                throw new ServiceException("请先下架：" + item.getSpuName());
            }
        });
        return cywProSpuInfoMapper.deleteCywProSpuInfoBySpuIds(spuIds);
    }

    /**
     * 删除spu信息信息
     *
     * @param spuId spu信息主键
     * @return 结果
     */
    @Override
    public int deleteCywProSpuInfoBySpuId(Long spuId) {
        return cywProSpuInfoMapper.deleteCywProSpuInfoBySpuId(spuId);
    }

    @Override
    public List<CywProSpuInfo> selectListBySpuIds(List<Long> spuIds) {
        return cywProSpuInfoMapper.selectListBySpuIds(spuIds);
    }

    @Override
    public int upPublishProduct(Long spuId) {
        // TODO es
        List<ProductInfoVO> cacheObject = redisCache.getCacheObject(CacheConstants.PRODUCT_CACHE + "info");
        List<CywProSpuInfo> proSpuInfoList = new ArrayList<>();
        CywProSpuInfo proSpuInfo = cywProSpuInfoMapper.selectCywProSpuInfoBySpuId(spuId);
        proSpuInfoList.add(proSpuInfo);
        List<ProductInfoVO> list = productService.buildProductInfoVOList(proSpuInfoList);
        List<Product> esProductList = productService.buildEsProductList(list);
        esProductMapper.insertBatch(esProductList);
        cacheObject.addAll(list);
        redisCache.setCacheObject(CacheConstants.PRODUCT_CACHE + "info", cacheObject);
        redisCache.deleteObject(CacheConstants.PRODUCT_CACHE + "search_condition");
        return cywProSpuInfoMapper.upPublishProduct(spuId);
    }

    @Override
    public int downPublishProduct(Long spuId) {
        // TODO es
        List<ProductInfoVO> cacheObject = redisCache.getCacheObject(CacheConstants.PRODUCT_CACHE + "info");
        redisCache.setCacheObject(CacheConstants.PRODUCT_CACHE + "info", cacheObject.stream().filter(item -> !item.getSpuId().equals(spuId)).collect(Collectors.toList()));
        ProductInfoVO productInfoVO = cacheObject.stream().filter(item -> item.getSpuId().equals(spuId)).findFirst().get();
        List<Long> skuIds = productInfoVO.getSkuInfos().stream().map(CywProSkuInfo::getSkuId).collect(Collectors.toList());
        esProductMapper.deleteBatchIds(skuIds);
        return cywProSpuInfoMapper.downPublishProduct(spuId);
    }
}
